import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import '../models/api_response.dart';
import '../models/user.dart';
import '../../core/exceptions/app_exception.dart';
import '../../core/constants/api_constants.dart';

/// 认证API服务
class AuthApi {
  final http.Client _client;

  AuthApi({http.Client? client}) : _client = client ?? http.Client();

  /// 发送认证请求的公共方法
  Future<Map<String, dynamic>> _sendAuthRequest({
    required String url,
    required Map<String, dynamic> body,
    String logPrefix = '请求',
  }) async {
    try {
      debugPrint('$logPrefix开始: $body');
      final uri = Uri.parse(url);
      debugPrint('请求URL: $uri');

      // 转换为JSON字符串
      final String jsonBody = jsonEncode(body);
      debugPrint('JSON请求体: $jsonBody');

      // 发送请求
      final response = await _client
          .post(
            uri,
            headers: {'Content-Type': 'application/json'},
            body: jsonBody,
          )
          .timeout(
            Duration(seconds: ApiConstants.timeout),
            onTimeout: () => throw NetworkException('请求超时，请检查网络连接'),
          );

      debugPrint('$logPrefix返回状态码: ${response.statusCode}');
      final responseBody = utf8.decode(response.bodyBytes);
      debugPrint('$logPrefix返回内容: $responseBody');

      // 处理服务器错误
      if (response.statusCode >= 500) {
        throw NetworkException('服务器错误(${response.statusCode}): $responseBody');
      }

      // 解析响应JSON
      Map<String, dynamic>? responseData;
      try {
        responseData = jsonDecode(responseBody) as Map<String, dynamic>?;
      } catch (e) {
        throw FormatException('返回数据格式错误: $responseBody');
      }

      if (responseData == null) {
        throw ApiException('服务器返回空数据');
      }

      return responseData;
    } catch (e) {
      debugPrint('$logPrefix异常: $e');
      if (e is AppException) rethrow;
      throw NetworkException('网络请求失败: ${e.toString()}');
    }
  }

  /// 用户注册
  Future<ApiResponse<void>> register({
    required String username,
    required String email,
    required String password,
  }) async {
    final responseData = await _sendAuthRequest(
      url: '${ApiConstants.baseUrl}${AuthApiConstants.register}',
      body: {'username': username, 'email': email, 'password': password},
      logPrefix: '注册',
    );

    final apiResponse = ApiResponse<void>.fromJson(responseData, (_) => null);

    if (!apiResponse.isSuccess) {
      if (apiResponse.code == 409) {
        throw UserExistsException(apiResponse.message);
      }
      throw ApiException(apiResponse.message, code: apiResponse.code);
    }

    return apiResponse;
  }

  /// 用户登录
  Future<ApiResponse<AuthResponse>> login({
    required String username,
    required String password,
  }) async {
    final responseData = await _sendAuthRequest(
      url: '${ApiConstants.baseUrl}${AuthApiConstants.login}',
      body: {'username': username, 'password': password},
      logPrefix: '登录',
    );

    if (responseData['code'] != 200) {
      // 处理错误响应
      final message = responseData['message'] as String? ?? '未知错误';
      final code = responseData['code'] as int? ?? 400;

      if (code == 401) {
        throw InvalidCredentialsException(message);
      }
      throw ApiException(message, code: code);
    }

    // 只有成功响应才尝试解析data
    final apiResponse = ApiResponse<AuthResponse>.fromJson(responseData, (
      data,
    ) {
      // 确保data不为null且是成功的响应
      if (data == null) {
        return null; // a允许空的data
      }
      try {
        return AuthResponse.fromJson(data as Map<String, dynamic>);
      } catch (e) {
        debugPrint('解析认证响应异常: $e, 原始数据: $data');
        throw ApiException('解析认证响应失败: ${e.toString()}');
      }
    });

    return apiResponse;
  }

  /// 刷新令牌
  Future<ApiResponse<AuthResponse>> refreshToken(String refreshToken) async {
    final responseData = await _sendAuthRequest(
      url: '${ApiConstants.baseUrl}${AuthApiConstants.refresh}',
      body: {'refresh_token': refreshToken},
      logPrefix: '刷新令牌',
    );

    if (responseData['code'] != 200) {
      // 处理错误响应
      final message = responseData['message'] as String? ?? '未知错误';
      final code = responseData['code'] as int? ?? 400;

      if (code == 401) {
        throw TokenExpiredException(message);
      }
      throw ApiException(message, code: code);
    }

    // 只有成功响应才尝试解析data
    final apiResponse = ApiResponse<AuthResponse>.fromJson(responseData, (
      data,
    ) {
      if (data == null) {
        return null;
      }
      return AuthResponse.fromJson(data as Map<String, dynamic>);
    });

    return apiResponse;
  }

  void dispose() {
    _client.close();
  }
}
